package Planificador;

import java.util.ArrayList;

public class Proceso {
	// instrucciones que se concumen por la cpu;
	protected ArrayList<Instruccion> instrucciones = new ArrayList<Instruccion>();
	protected ArrayList<Instruccion> instruccionesNoConsumibles = new ArrayList<Instruccion>();
	protected int entradaAlSistema;
	protected String nombre;
	protected Instruccion instruccionActual = null;
	protected int prioridad = 0;
	private int tiempoEnProcesador = 0;

	public Proceso(String nombre) {
		this.entradaAlSistema = 0;
		this.nombre = nombre;
	}

	public void inicializar() {
		this.instruccionActual = null;
		this.tiempoEnProcesador = 0;
		this.instrucciones.clear();

		for (Instruccion instruccion : instruccionesNoConsumibles) {
			instruccion.inicializar();
		}

		this.instrucciones.addAll(this.instruccionesNoConsumibles);
	}

	public Proceso(String nombre, int entradaAlSistema, int prioridad) {
		this.entradaAlSistema = entradaAlSistema;
		this.nombre = nombre;
		this.prioridad = prioridad;
	}

	public Proceso(String nombre, int entradaAlSistema) {
		this.entradaAlSistema = entradaAlSistema;
		this.nombre = nombre;
	}

	@Override
	public String toString() {
		return this.nombre;
	}

	public Proceso addInstruccion(Instruccion instruccion) {
		int i = this.instruccionesNoConsumibles.size();
		// control para que no haga dos instrucciones del mismo tipo seguidas
		if (i > 0
				&& instruccion.getClass() == this.instruccionesNoConsumibles
						.get(i - 1).getClass()) {
			return this;
		}
		this.instruccionesNoConsumibles.add(instruccion);

		return this;
	}

	public int getRafagaSiguiente() {
		if (this.instruccionActual instanceof InstruccionUsoCpu) {
			return this.instruccionActual.getRafaga();
		}

		for (Instruccion i : instrucciones) {
			if (i instanceof InstruccionUsoCpu) {
				return i.getRafaga();
			}
		}
		return 0;
	}

	public Proceso setPrioridad(int i) {
		this.prioridad = i;
		return this;
	}

	public int getPrioridad() {
		return this.prioridad;
	}

	public Instruccion getInstruccion() {
		return this.instruccionActual;
	}

	public void recibirQuantum() throws FinDeProcesoException,
			ConsumioTodaLaRafagaCpuException,
			ConsumioTodaLaRafagaEntradaSalidaException {
		if (this.instruccionActual == null) {
			this.setSiguienteInstruccion();
		}

		try {
			this.instruccionActual.recibirQuantum();
		} catch (ConsumioTodaLaRafagaCpuException e) {
			this.setSiguienteInstruccion();
			throw new ConsumioTodaLaRafagaCpuException();
		} catch (ConsumioTodaLaRafagaEntradaSalidaException e) {
			this.setSiguienteInstruccion();
			throw new ConsumioTodaLaRafagaEntradaSalidaException();
		}
	}

	private void setSiguienteInstruccion() throws FinDeProcesoException {
		if (this.instrucciones.size() == 0) {
			throw new FinDeProcesoException();
		}
		this.instruccionActual = this.instrucciones.get(0);
		this.instrucciones.remove(0);
	}

	public void moverseAsigInstruccion() {
		this.instruccionActual.moverseADispositivo(this);
	}

	public int getTiempoEntrada() {
		return this.entradaAlSistema;
	}

	public int getTiempoEnProcesador() {
		return this.tiempoEnProcesador;
	}

	public void setTiempoEnProcesador(int i) {
		this.tiempoEnProcesador = i;
	}
}
